#!/usr/bin/perl -w

BEGIN {
	push @INC,"../lib";
}

use Data::Dumper;
use lvm;
use strict;
use Getopt::Long;

$::ARG_test=undef;
$::ARG_vgname=undef;
$::ARG_lvname=undef;
$::ARG_size=undef;

sub usage {
	print "
Usage: lvm-test --test=N --vgname=X [--lvname=X] [--size=N]

The lvm-test routine takes an existing volume group and performs a number of
tests on it, the test being determined by the number in question [see below].
If all tests are passed successfully then this machine and vg are considered
suitable for use in a TruCL cluster.

The arguments currently supported are:

--test		The number of the test to perform.
--vgname	The name of the volume group to create logical volume in.
--lvname	The name of the logical volume to create.
--size		The size [in mb] of the logical volume to create.

At present the supported tests are:

0  - Check to see whether standard commands are available
1  - Generate a list of supported volume managers on host
2  - Generate a list of all volume groups and there types

11 - Create a logical volume
12 - Grow in a size an existing logical volume by 8Mb
13 - Destroy existing logical volume
14 - Deport volume group - by careful!
15 - Import volume group - by careful!
16 - Display info on specified logical volume
17 - Display info on all logical volumes.

Written by Simon Edwards, (C) 2009-2011, www.advantsys.co.uk
";
	exit(1);
}

if(!GetOptions(
	"test=i"	=> \$::ARG_test,
	"size=i"	=> \$::ARG_size,
	"vgname=s"	=> \$::ARG_vgname,
	"lvname=s"	=> \$::ARG_lvname
)) {
	usage();
}

if(!defined($::ARG_test)) {
	usage();
}

$::LVM=new lvm();

if(!defined($::LVM)) {
	print STDERR "Error: Unable to define LVM object - aborting!\n";
	exit(1);
}

if($::ARG_test==0) {
	my $t=$::LVM->has_cmds();
	print "Test 0: Available LVM commands\n";
	print "==============================\n";
	my @F=split(/,/,$t);
	for my $ct (@F) {
		my @F2=split(/\s+/,$ct);
		my $desc=$::LVM->describe_type($F2[0]);
		if($F2[1]==1) {
			print "* $F2[0] [$desc] - Commands present.\n";
		} else {
			print "* $F2[0] [$desc] - Commands absent.\n";
		}
	}	
	exit(0);
}

if($::ARG_test==1) {
	my $t=$::LVM->type();
	print "Test 1: Support LVM types\n";
	print "=========================\n";
	my @F=split(/,/,$t);
	for my $ct (@F) {
		my $desc=$::LVM->describe_type($ct);
		print "* $ct [$desc]\n";
	}	
	exit(0);
}

if($::ARG_test==2) {
	print "Test 2: List existing [imported] Volume groups and types\n";
	print "========================================================\n";
	my @vgs=$::LVM->vg_list();
	for my $cvg (sort @vgs) {
		my ($a,$b)=split(/\s+/,$cvg);
		print "* $a [Type $b]\n";
	}
	exit(0);
}

if($::ARG_test==11) {
	if(!defined($::ARG_vgname) || !defined($::ARG_lvname) || !defined($::ARG_size)) {
		print STDERR "Error: Test 11 requires --vgname, --lvname and --size setting.\n";
		exit(1);
	}
	if($::ARG_size<20) {
		print STDERR "Error: Size specified is too small [must be >=20].\n";
		exit(1);
	}
	# Firstly check if the vg is available.
	my @vginfo=$::LVM->lv_list(VGNAME => $::ARG_vgname);
	if(!defined($vginfo[0])) {
		print STDERR "Error: Volume group '$::ARG_vgname' is unknown.\n";
		exit(1);
	}
	# Check to ensure the specified volume disk not exist.
	if(grep {$_ eq $::ARG_lvname} @vginfo) {
		print STDERR "Error: Logical volume '$::ARG_lvname' already exists.\n";
		exit(1);
	}

	# Now create the logical volume
	my ($a,$b)=$::LVM->lvcreate(VGNAME=>$::ARG_vgname,LVNAME=>$::ARG_lvname,SIZE=>1024*$::ARG_size);
	if($a!=0) {
		print STDERR "Error: $b\n";
		exit(1);
	}
	
	my @r=$::LVM->get_lvinfo(VGNAME=>$::ARG_vgname,LVNAME=>$::ARG_lvname,UPTODATE=>1);
	if(!defined($r[0])) {
		print STDERR "Error: Logical volume was not created.\n";
		exit(1);
	}
	if($r[1] != $::ARG_size*1024) {
		my $x1=1024*$::ARG_size;
		print STDERR "Error: Volume created, but of different size [Requested=$x1,Actual=$r[1]]\n";
		exit(1);
	}
	exit(0);
}

if($::ARG_test==12) {
	if(!defined($::ARG_vgname) || !defined($::ARG_lvname)) {
		print STDERR "Error: Test 12 requires --vgname and --lvname.\n";
		exit(1);
	}

	# make sure the specified logical volume already exists, and if it does
	# not then we need to abort asap.

	my @vginfo=$::LVM->lv_list(VGNAME => $::ARG_vgname);
	if(!defined($vginfo[0])) {
		print STDERR "Error: Volume group '$::ARG_vgname' is unknown.\n";
		exit(1);
	}
	# Check to ensure the specified volume disk not exist.
	if(! grep {$_ eq $::ARG_lvname} @vginfo) {
		print STDERR "Error: Logical volume '$::ARG_lvname' does not yet exist.\n";
		exit(1);
	}

	# Get the current size which can then increase...
	my @r=$::LVM->get_lvinfo(VGNAME=>$::ARG_vgname,LVNAME=>$::ARG_lvname);
	if(!defined($r[0])) {
		print STDERR "Error: Logical volume information not found!\n";
		exit(1);
	}
	my $csize=$r[1];
	$csize+=8192;
	my ($a,$b)=$::LVM->lvresize(VGNAME=>$::ARG_vgname,LVNAME=>$::ARG_lvname,SIZE=>$csize);
	if($a!=1) {
		print STDERR "Error: $b\n";
		exit(1);
	}
	# Issue a 'note' if the size is different than requested.
	if($b != $csize) {
		print "Note: Actual size different than requested [requested=$csize,actual=$b]\n";
	}
	print "Volume resized successfully.\n";
	exit(0);
}

if($::ARG_test==13) {
	if(!defined($::ARG_vgname) || !defined($::ARG_lvname)) {
		print STDERR "Error: Test 13 requires --vgname and --lvname.\n";
		exit(1);
	}

	# make sure the specified logical volume already exists, and if it does
	# not then we need to abort asap.

	my @vginfo=$::LVM->lv_list(VGNAME => $::ARG_vgname);
	if(!defined($vginfo[0])) {
		print STDERR "Error: Volume group '$::ARG_vgname' is unknown.\n";
		exit(1);
	}
	# Check to ensure the specified volume disk already exists
	if(! grep {$_ eq $::ARG_lvname} @vginfo) {
		print STDERR "Error: Logical volume '$::ARG_lvname' does not exist.\n";
		exit(1);
	}

	# Now remove it...
	my @r=$::LVM->get_lvinfo(VGNAME=>$::ARG_vgname,LVNAME=>$::ARG_lvname);
	if(!defined($r[0])) {
		print STDERR "Error: Logical volume information not found!\n";
		exit(1);
	}
	my ($a,$b)=$::LVM->lvremove(VGNAME=>$::ARG_vgname,LVNAME=>$::ARG_lvname);
	if($a!=1) {
		print STDERR "Error: $b\n";
		exit(1);
	}
	print "Volume successfully removed.\n";
	exit(0);
}

if($::ARG_test==14) {
	if(!defined($::ARG_vgname)) {
		print STDERR "Error: Test 14 requires --vgname.\n";
		exit(1);
	}
	# Check that the volume group is imported first, and if not give error.
	my @vginfo=$::LVM->lv_list(VGNAME => $::ARG_vgname);
	if(!defined($vginfo[0])) {
		print STDERR "Error: Volume group '$::ARG_vgname' is unknown or not currently imported.\n";
		exit(1);
	}
	
	# deport it then...
	my ($rc,$err)=$::LVM->vg_deactivate(VGNAME=>$::ARG_vgname);
	if($rc!=0) {
		print STDERR "Error: $err\n";
		exit(1);
	}
	print "Volume group deported/exported/deactivated successfully.\n";
	exit(0);
}

# Importing does not need to know the type of the volume group - it will
# try importing against all supported volume managers!

if($::ARG_test==15) {
	if(!defined($::ARG_vgname)) {
		print STDERR "Error: Test 15 requires --vgname.\n";
		exit(1);
	}
	# Check that the volume group is NOT imported first, and if so give error.
	my @vginfo=$::LVM->lv_list(VGNAME => $::ARG_vgname);
	if(defined($vginfo[0])) {
		print STDERR "Error: Volume group '$::ARG_vgname' is already imported.\n";
		exit(1);
	}
	
	# deport it then...
	my ($rc,$err)=$::LVM->vg_activate(VGNAME=>$::ARG_vgname);
	if($rc!=0) {
		print STDERR "Error: $err\n";
		exit(1);
	}
	print "Volume group imported/activated successfully.\n";
	exit(0);
}

if($::ARG_test==16) {
	if(!defined($::ARG_vgname) || !defined($::ARG_lvname)) {
		print STDERR "Error: Test 16 requires --vgname and lvname.\n";
		exit(1);
	}

	my @r=$::LVM->get_lvinfo(VGNAME=>$::ARG_vgname,LVNAME=>$::ARG_lvname);
	if(!defined($r[0])) {
		print STDERR "Error: Logical volume information not found for $::ARG_vgname/$::ARG_lvname!\n";
		exit(1);
	}

	print "Status : $r[0]\n";
	print "Size   : $r[1]\n";
	print "Open   : $r[2]\n";
	exit(0);
}

if($::ARG_test==17) {
	# Firstly get a list of all volume groups...

	my @vgnames=$::LVM->vg_list();
	for my $cvg_info (@vgnames) {
		my ($cvg,$cvg_type)=split(/\s+/,$cvg_info);
		my @lvlist=$::LVM->lv_list(VGNAME => $cvg);
		if(!defined($lvlist[0])) {
			print STDERR "Error: Did not return lvlist for '$cvg'.\n";
			exit(1);
		}
		print "\nVG     : $cvg\n";
		for my $clv (@lvlist) {
			my @r=$::LVM->get_lvinfo(VGNAME=>$cvg,LVNAME=>$clv);
			print "Name   : $clv\n";
			print "Status : $r[0]\n";
			print "Size   : $r[1]\n";
			print "Open   : $r[2]\n";

		}
	}
	exit(0);
}

